Skip to content

Conversation

@ShivaGupta-14
Copy link
Contributor

Description

When multiple const or enum constraints fail (e.g., via allOf), produce a single message with the most restrictive constraint instead of multiple redundant messages.

  • Compute the intersection of allowed values across all constraints
  • If intersection has 1 value: use const message
  • If intersection has multiple values: use enum message
  • If intersection is empty (contradictory): use boolean schema message
  • Fixes: Combine const and enum handlers #132

Checklist

  • npm test
  • npm run lint
  • npm run type-check

@ShivaGupta-14 ShivaGupta-14 force-pushed the 132-combine-const-enum-handlers branch from 7646a94 to ac73647 Compare January 30, 2026 18:24
Copy link
Collaborator

@jdesrosiers jdesrosiers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach isn't going to work. Try,

{
  "allOf": [
    { "const": "a" },
    { "const": "b" }
  ]
}

@ShivaGupta-14 ShivaGupta-14 force-pushed the 132-combine-const-enum-handlers branch from ac73647 to 3b4eaf2 Compare January 31, 2026 15:51
@ShivaGupta-14
Copy link
Contributor Author

ShivaGupta-14 commented Jan 31, 2026

This approach isn't going to work. Try,

{
  "allOf": [
    { "const": "a" },
    { "const": "b" }
  ]
}

Hi @jdesrosiers,

thanks for pointing out the issue! I understood the problem:

Issue: with a schema like above one -> allOf: [{ const: "a" }, { const: "b" }], if the instance is "a"

  • const: "a" passes (not in errors)
  • Only const: "b" fails
  • My original code only saw failing constraints -> couldn't detect the contradiction
  • My Solution: I updated the handler to collect ALL constraints (both passing and failing), then compute the intersection:
const passed = normalizedErrors[...][schemaLocation] === true;
if (!passed) hasFailure = true;
// always collect
constraints.push({ allowedValues: [...], schemaLocation });

now:

  • Both ["a"] and ["b"] are collected
  • Intersection = [] (empty)
  • Returns getBooleanSchemaErrorMessage()

Tests Added:

  • contradictory const - empty intersection (instance matches one const)
  • contradictory enum - empty intersection (disjoint enum sets)

All tests pass. Is this approach good, or does it need further improvements?
Thanks!

Copy link
Collaborator

@jdesrosiers jdesrosiers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should work. Just a couple small things I'd like to see.

Comment on lines 57 to 67
const sorted = [...constraints].sort((a, b) =>
a.allowedValues.length - b.allowedValues.length
);
const mostConstraining = sorted[0];

let intersection = mostConstraining.allowedValues;
for (let i = 1; i < sorted.length; i++) {
intersection = intersection.filter((/** @type {Json} */ val) =>
sorted[i].allowedValues.some((/** @type {Json} */ other) => jsonEqual(val, other))
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this could be avoided if you used a Set and Set operations to determine the intersection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored to use Set operations for intersection, thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is exactly the same code. All you did was wrap your array in a Set and then convert it back to an array. Have look at Set.intersection and try again.

Copy link
Contributor Author

@ShivaGupta-14 ShivaGupta-14 Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdesrosiers

yes, I looked into Set.intersection() but didn't use it due to compatibility concerns, it requires Node 22+, Chrome 122+, Safari 17+

The manual approach ensures broader compatibility. should I switch to Set.intersection(), or is the manual approach preferred for this project?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Use Set.intersection.

@ShivaGupta-14 ShivaGupta-14 force-pushed the 132-combine-const-enum-handlers branch from 3b4eaf2 to e7b9dec Compare February 2, 2026 12:19
@ShivaGupta-14 ShivaGupta-14 force-pushed the 132-combine-const-enum-handlers branch from e7b9dec to 219a62a Compare February 2, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Combine const and enum handlers

2 participants